/**
 * 
 */
package jgrit.gui.img;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.File;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.UIManager;

import jgrit.gui.FileDrop;
import jgrit.gui.FileSelector;
import jgrit.gui.export.ExportDialog;
import jgrit.options.OptionCollection;

/**
 * Basic image viewer
 * 
 * @author Sam Hartsfield
 */
public class ImageViewer {
	
	/** Version identifier */
	private static final long serialVersionUID = 8091983335338036762L;
	
	private OptionCollection options = new OptionCollection();
	
	/**
	 * Preferred height and width
	 */
	private static int PREF_WIDTH = 400, PREF_HEIGHT = 300;
	
	/**
	 * The top-level frame 
	 */
	private JFrame frame;
	
	/**
	 * The top-level panel
	 */
	private JPanel panel;

	/**
	 * The image-drawing canvas
	 */
	private ImageCanvas canvas;
	
	/**
	 * Action to open a file
	 */
	private Action openAction;
	
	/**
	 * Action to show the about box
	 */
	private Action aboutAction;
	
	/**
	 * Action to call the export dialog with the loaded image
	 */
	private Action gbaExportAction;
	
	/**
	 * Object that will handle selecting image files
	 */
	private FileSelector fileSelector = new FileSelector();
	
	/**
	 * Action to exit
	 */
	private Action exitAction = new AbstractAction("Exit") {
		private static final long serialVersionUID = 1L;

		public void actionPerformed(ActionEvent e) {
			System.exit(0);
		}
	};
	/*instance*/ {
		exitAction.putValue(Action.ACCELERATOR_KEY, getAcceleratorKeyStroke(KeyEvent.VK_Q));
		if (System.getProperty("os.name").startsWith("Mac")) {
			// MacOS: The Exit menuitem should be displayed as Quit instead
			exitAction.putValue(Action.NAME, "Quit");
		}
	}
	
	
	/***************************************************************************
	 * 							  SET LOOK & FEEL
	 **************************************************************************/
	
	static {
		if (!System.getProperty("os.name").startsWith("Mac")) {
			// Set Look & Feel on Linux and Windows
			try {
				UIManager.setLookAndFeel("com.jgoodies.looks.plastic.PlasticXPLookAndFeel");
			} catch (Exception e) {
				// Don't set a L&F
			}
		}
	}
	
	
	/**
	 * Initialize the viewer
	 */
	public ImageViewer() {
		initActions();
		initGUI();
	}

	/**
	 * Set up the frame and the main panel
	 */
	private void initGUI() {
		frame = new JFrame("JGrit Image Viewer");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		panel = new JPanel(new BorderLayout());
		new FileDrop(panel, new FileDrop.Listener() {
			public void filesDropped(File[] files) {
					//Only care about the first of the selected files
					if (files.length > 0) {
						String fileName = files[0].getName();
						if (fileName != null && 
								FileSelector.verifyFileType(fileName)) {
							canvas.loadImage(files[0]);
							options.setFile(files[0]);
							options.setImage(canvas.getImg());
							
							gbaExportAction.setEnabled(true);
						}
				}
			}
		});
		
		createToolBar();
    	panel.setOpaque(true); //content panes must be opaque
    	frame.setContentPane(panel);
		
		String title = "JGrit Image Viewer";
    	if (getVersion() != null) {
    		title += " (SVN revision " + getVersion() + ")";
    	}
		
		frame.setJMenuBar(createMenuBar());
		
		canvas = new ImageCanvas();
		JScrollPane scrollpane = new JScrollPane(canvas);
		panel.add(scrollpane, BorderLayout.CENTER);
		
		setImageIcon();
		
		frame.pack();
		frame.setMinimumSize(frame.getSize());
		
		/*
		 * Just in case the preferred height or width should ever be less
		 * than the arbitrary sizes set here, compare to the current size.
		 */
		Dimension size = frame.getSize();
		if (size.height < PREF_HEIGHT) size.height = PREF_HEIGHT;
		if (size.width < PREF_WIDTH) size.width = PREF_WIDTH;		
		frame.setSize(size);
		
    	frame.setLocationRelativeTo(null);
	}
	
	/**
	 * Set the image icon of the window to the JGrit icon
	 */
	private void setImageIcon() {
		frame.setIconImage(new ImageIcon(getClass()
			.getResource("/jgrit/gui/icons/jgritIcon.png")).getImage());
	}
	
	/**
	 * Create the actions
	 */
	private void initActions() {
		// ---------- FILE ACTIONS --------------------------------------------
		
		openAction = new AbstractAction("Open", new ImageIcon(getClass().getResource("/jgrit/gui/icons/folder_picture.png"))) {
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) {
				String fileName = fileSelector.selectImageFile(frame);
				if (fileName != null) {
					File file = new File(fileName);
					canvas.loadImage(file);
					options.setFile(file);
					options.setImage(canvas.getImg());
					
					gbaExportAction.setEnabled(true);
				}
			}
		};
		openAction.putValue(Action.ACCELERATOR_KEY, getAcceleratorKeyStroke(KeyEvent.VK_O));
		
		gbaExportAction = new AbstractAction("GBA Export", new ImageIcon(
				getClass().getResource("/jgrit/gui/icons/door_out_flipped.png"))) {
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) {
				ExportDialog.showGUI(frame, options);
			}
		};
		gbaExportAction.putValue(Action.ACCELERATOR_KEY, getAcceleratorKeyStroke(KeyEvent.VK_E));
		
		/*
		 * Start disabled until an image is loaded.
		 */
		gbaExportAction.setEnabled(false);
		
		
		// ---------- HELP ACTIONS --------------------------------------------		
		aboutAction = new AbstractAction("About...") {
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) {
				String version = getVersion();
				if (version == null) {
					version = "not available";
				}
				JOptionPane.showMessageDialog(frame, "SVN version: " + version
						+ "\n\n" + 
						"To get more information, submit feedback, " +
						"or download the source code, visit " +
						"http://jgrit.googlecode.com",
						"About", JOptionPane.INFORMATION_MESSAGE);
			}
		};
	}
	
	private static KeyStroke getAcceleratorKeyStroke(int keyCode) {
		int modifiers = System.getProperty("os.name").startsWith("Mac")
				? InputEvent.META_DOWN_MASK : InputEvent.CTRL_DOWN_MASK;
		return KeyStroke.getKeyStroke(keyCode, modifiers);
	}
	
	/**
	 * Returns the SVN revision number, retrieved from the manifest file (so
	 * it is only available when being run from a JAR).
	 * 
	 * @return The version string, or null if undefined
	 */
	public String getVersion() {
		return this.getClass().getPackage().getImplementationVersion();
	}
	
    /**
     * Create the toolbar, attaching the actions
     */
    private void createToolBar() {
        JButton button = null;

        //Create the toolbar.
        JToolBar toolBar = new JToolBar();
        panel.add(toolBar, BorderLayout.NORTH);

        //first button
        button = new JButton(openAction);
        if (button.getIcon() != null) {
            button.setText(""); //an icon-only button
        }
        toolBar.add(button);

        //second button
        button = new JButton(gbaExportAction);
        if (button.getIcon() != null) {
            button.setText(""); //an icon-only button
        }
        toolBar.add(button);
    }
    

    /**
     * @return The Image Viewer menu bar (JMenuBar)
     */
    public JMenuBar createMenuBar() {
    	JMenuBar menuBar = new JMenuBar();
    	
    	// ---------- FILE MENU ----------------------------------------------
    	JMenu fileMenu = new JMenu("File");
    	fileMenu.setMnemonic(KeyEvent.VK_F);
    	menuBar.add(fileMenu);
    	
    	fileMenu.add(openAction);
    	fileMenu.add(gbaExportAction);
    	
    	fileMenu.addSeparator();
    	
    	fileMenu.add(exitAction);
    	
    	// ---------- HELP MENU ----------------------------------------------
    	JMenu helpMenu = new JMenu("Help");
    	helpMenu.setMnemonic(KeyEvent.VK_H);
    	menuBar.add(helpMenu);

    	helpMenu.add(aboutAction);
    	
    	return menuBar;
    }

    /**
     * Make the frame visible or not
     * @param visible true sets visible, false sets invisible
     */
    public void setVisible(boolean visible) {
    	frame.setVisible(visible);
    }

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ImageViewer iv = new ImageViewer();
		iv.setVisible(true);
	}

}
